package com.zlyx.easy.api;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.zlyx.easy.api.annotations.ApiGroup;
import com.zlyx.easy.api.config.SwaggerConfigurer;
import com.zlyx.easy.api.reader.ApiReader;
import com.zlyx.easy.api.register.ApiRegister;
import com.zlyx.easy.api.store.ApiCache;
import com.zlyx.easy.core.annotations.ApplicationBean;
import com.zlyx.easy.core.event.IHandlerOnRefreshed;
import com.zlyx.easy.core.list.Lists;
import com.zlyx.easy.core.map.Maps;
import com.zlyx.easy.core.tool.Ops;
import com.zlyx.easy.core.utils.ProxyUtils;
import com.zlyx.easy.core.utils.RequestUtils;
import com.zlyx.easy.core.utils.SpringUtils;

import io.swagger.models.Swagger;
import io.swagger.util.Json;

/**
 * @Auth 赵光
 * @Describle
 */
@ApplicationBean(todo = { "Api管理中心" })
public class ApiManager implements IHandlerOnRefreshed {

	private static Map<String, String> swaggers = Maps.newMap();

	private static Map<String, Map<Class<?>, Object>> refs = Maps.newMap();

	private static Map<Class<?>, Object> interfaceMapRef = new ConcurrentHashMap<Class<?>, Object>();

	@Autowired(required = false)
	private ApiCache cache;

	@SuppressWarnings("unchecked")
	@Override
	public void doOnRefreshed(ApplicationContext context) throws Exception {
		swaggers.clear();
		refs.clear();
		interfaceMapRef.clear();
		if (cache != null && cache.isUse()) {
			swaggers.putAll(JSONObject.parseObject(cache.getApis(), Map.class));
		}
		Map<String, Object> beans = Maps.newMap();
		beans.putAll(SpringUtils.getBeanswithAnnotation(ApiGroup.class));
		beans.putAll(SpringUtils.getBeansOfType(ApiRegister.class));
		Map<Class<?>, Object> beanMap = null;
		ApiGroup apiGroup = null;
		for (String name : beans.keySet()) {
			beanMap = Maps.newMap();
			if (beans.get(name) != null && beans.get(name) instanceof ApiRegister) {
				beanMap.putAll(((ApiRegister) beans.get(name)).register(context));
			}
			apiGroup = ProxyUtils.getTarget(beans.get(name)).getClass().getAnnotation(ApiGroup.class);
			if (apiGroup != null) {
				Class<?>[] clses = apiGroup.clses();
				if (clses.length > 0) {
					for (Class<?> cls : clses) {
						beanMap.putAll(SpringUtils.getBeanMapByCls(cls));
					}
				}
				if (Ops.isNotEmpty(apiGroup.group())) {
					name = apiGroup.group();
				}
			}
			if (!beanMap.isEmpty()) {
				refs.put(name, beanMap);
				interfaceMapRef.putAll(beanMap);
				if (cache == null || !cache.isUse()) {
					swaggers.put(name, null);
				}
			}
		}
		if (cache != null && !cache.isUse()) {
			for (Entry<String, Map<Class<?>, Object>> entry : refs.entrySet()) {
				Map<Class<?>, Object> interfaceMapRef = entry.getValue();
				Swagger swagger = SwaggerConfigurer.getSwagger();
				ApiReader.read(interfaceMapRef, swagger);
				ApiManager.registerSwagger(entry.getKey(), swagger);
			}
			cache.saveApi(JSON.toJSONString(swaggers));
		}
	}

	public static Map<Class<?>, Object> interfaceMapRef(String groupName) {
		return refs.get(groupName);
	}

	/**
	 * 根据类名获取
	 * 
	 * @param interfaceClass
	 * @return
	 */
	public static Entry<Class<?>, Object> getRef(String interfaceClass) {
		Set<Entry<Class<?>, Object>> entrySet = interfaceMapRef.entrySet();
		for (Entry<Class<?>, Object> entry : entrySet) {
			if (entry.getKey().getName().equals(interfaceClass)) {
				return entry;
			}
		}
		return null;
	}

	public static String getSwagger(String groupName) {
		return swaggers.get(groupName);
	}

	public static Map<String, List<String>> getGroupNames() {
		return Maps.newMap(RequestUtils.getHost(), Lists.newList(swaggers.keySet()));
	}

	public static String registerSwagger(String groupName, Swagger swagger) throws JsonProcessingException {
		swaggers.put(groupName, Json.mapper().writeValueAsString(swagger));
		return getSwagger(groupName);
	}
}
